
#include "DataUpdata.h"

#include "Configure.h"
#include "Server.h"
#include "Util.h"
#include "dataShare/include/ApplicationLayer.h"

#include <cstdlib>
#include <cstring>
#include <hal_time.h>
#include <iec61850_model.h>
#include <iec61850_server.h>
#include <memory>
#include <mms_value.h>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include <zlog.h>

bool                                         DataUpdate::b_num = false;
std::unordered_map<std::string, std::string> DataUpdate::varNameMap;

DataUpdate::DataUpdate() {}

DataUpdate::~DataUpdate() {}

void DataUpdate::Init() {
    appLayer = ApplicationLayer::GetInstance();
    if (appLayer == nullptr) {
        zlog_e("AppLayer is nullptr");
        exit(-1);
    }

    int sAddr = 1;
    for (sAddr = 1; sAddr < SADDR_MAX_NUM; sAddr++) {
        DataAttribute *attr =
            (DataAttribute *)IedModel_getModelNodeByShortAddress(&iedModel,
                                                                 sAddr);

        std::string varName = Util::GetVarName((ModelNode *)attr);
        if (!varName.empty()) {
            varNameMap[varName] = "";
        }
    }

    zlog_i("varNameMap size: %ld", varNameMap.size());

    int index = 1;
    for (auto it = varNameMap.begin(); it != varNameMap.end(); it++) {
        zlog_i("varName[%03d]: %s", index++, it->first.c_str());
    }
}

void DataUpdate::Query() {
    int ret = appLayer->QueryData(varNameMap);
    if (ret != ErrorInfo::OK) {
        zlog_e("redis query failed, ret: %d", ret);
        for (auto &it : varNameMap) {
            it.second = "0";
        }
    }
    zlog_i("varNameMap size: %ld", varNameMap.size());
    return;
}

void DataUpdate::Update() {
    DataAttribute *attr = NULL;
    for (int sAddr = 1; sAddr < SADDR_MAX_NUM; sAddr++) {
        attr = (DataAttribute *)IedModel_getModelNodeByShortAddress(&iedModel,
                                                                    sAddr);
        if (attr == NULL) {
            zlog_e("Get Model From Short Address Failed, sAddr: %d", sAddr);
            return;
        }

        std::string varName = Util::GetVarName((ModelNode *)attr);
        if (varName.empty()) {
            // filter out the Beh , Mod and Health
            continue;
        }

        auto        var     = varNameMap.find(varName);
        std::string dataStr = var->second;
        if (dataStr.empty()) {
            zlog_e("dataStr is empty, varName: %s", varName.c_str());
            continue;
        }

        if (MmsValue_getType(attr->mmsValue) == MMS_BOOLEAN) {
            IedServer_updateBooleanAttributeValue(
                Server::iedServer, attr, dataStr == "1" ? true : false);
        }
        else if (MmsValue_getType(attr->mmsValue) == MMS_FLOAT) {
            try {
                IedServer_updateFloatAttributeValue(
                    Server::iedServer, attr, std::stof(dataStr));
            }
            catch (const std::invalid_argument &e) {
                zlog_e("std::invalid_argument: %s", e.what());
            }
            catch (const std::out_of_range &e) {
                zlog_e("std::out_of_range: %s", e.what());
            }
        }
        else if (MmsValue_getType(attr->mmsValue) == MMS_INTEGER) {
            try {
                IedServer_updateInt32AttributeValue(
                    Server::iedServer, attr, std::stoi(dataStr));
            }
            catch (const std::invalid_argument &e) {
                zlog_e("<%s> std::invalid_argument: %s",
                       varName.c_str(),
                       e.what());
            }
            catch (const std::out_of_range &e) {
                zlog_e("std::out_of_range: %s", e.what());
            }
        }
        else if (MmsValue_getType(attr->mmsValue) == MMS_UTC_TIME) {
            IedServer_updateUTCTimeAttributeValue(
                Server::iedServer, attr, Hal_getTimeInMs());
        }
        else if (MmsValue_getType(attr->mmsValue) == MMS_BINARY_TIME) {
            zlog_i("更新UTC 时间戳");
            IedServer_updateUTCTimeAttributeValue(
                Server::iedServer, attr, Hal_getTimeInMs());
        }
        else if (MmsValue_getType(attr->mmsValue) == MMS_BIT_STRING) {
            IedServer_updateBitStringAttributeValue(
                Server::iedServer, attr, QUALITY_VALIDITY_GOOD);
        }
        else {
            zlog_i("未知数据类型, type: %d, addr: %d",
                   MmsValue_getType(attr->mmsValue),
                   attr->sAddr);
        }
    }
}

void DataUpdate::Run() {
    Query();
    Update();

    int count = 1;
    // 显示数据的值
    for (auto it = varNameMap.begin(); it != varNameMap.end(); it++) {
        zlog_i("varName[%03d]: %s, value: %s",
               count++,
               it->first.c_str(),
               it->second.c_str());
    }
}
